﻿using ArtMath.Attribute;
using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Flag;
using ArtMath.Helper;
using ArtMath.PointCollection;
using ArtMath.Resource;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace ArtMath.Component.Polygon
{
    /// <summary>
    /// 直角梯形
    /// </summary>
    [Serializable]
    public class RightAngledTrapezoid : TrapezoidBase
    {
        double rate;
        public RightAngledTrapezoid(SketchPad pad, string name, bool addToList = true) : base(pad, name, ToolTypeName.zjtx, addToList)
        {

        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("RightAngleWaist")]
        public override LineSegmentBase Waist1
        {
            get
            {
                return base.Waist1;
            }

            set
            {
                base.Waist1 = value;
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("SlantingWaist")]
        public override LineSegmentBase Waist2
        {
            get
            {
                return base.Waist2;
            }

            set
            {
                base.Waist2 = value;
            }
        }
        public override int ClickTimes
        {
            get
            {
                if (OrderIndex == 2 || OrderIndex == 3)
                {
                    return 3;
                }
                return base.ClickTimes;
            }
        }
        public override void ComponentBuilding(Base component)
        {
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}");
            switch (OrderIndex)
            {
                case 0:
                    if (component == Hemline1)
                    {
                        Hemline1.SpareCoordinate_ = Hemline1.SpareCoordinate.GetProjectivePoint(Hemline1.Point1.Pxy, Pad.kToPk(-1 / Waist1.Slope));
                        return;
                    }
                    else if (component == Waist2)
                    {
                        Waist2.AllowFix = false;
                        Waist2.SpareCoordinate_ = Utility.GetCrossPoint(Waist2.Point1.Pxy, Waist2.PSlope, Waist1.Point1.Pxy, Hemline1.PSlope);
                        Waist2.AllowFix = true;
                        PointD h2 = Pad.PxyToXY(Waist2.SpareCoordinate);
                        double db2len = Waist1.Point1.ToPointD().DistanceTo(h2);
                        Circumference = Waist1.Length + Hemline1.Length + Waist2.Length + db2len;
                        Area = (Hemline1.Length + db2len) * Waist1.Length / 2;
                        BaryCenter = Utility.GetBaryCenter(new PointD[] { Waist1.Point1.ToPointD(), Hemline1.Point1.ToPointD(), Waist2.Point1.ToPointD(), h2 });
                    }
                    else
                    {
                        return;
                    }
                    break;
                case 1:
                    if (component == Waist1)
                    {
                        Waist1.SpareCoordinate_ = Waist1.SpareCoordinate.GetProjectivePoint(Waist1.Point1.Pxy, Pad.kToPk(-1 / Hemline1.Slope));
                        return;
                    }
                    else if (component == Hemline2)
                    {
                        Hemline2.SpareCoordinate_ = Hemline2.SpareCoordinate.GetProjectivePoint(Hemline2.Point1.Pxy, Hemline1.PSlope);
                        PointD w2 = Pad.PxyToXY(Hemline2.SpareCoordinate);
                        Circumference = Hemline1.Length + Waist1.Length + Hemline2.Length + Hemline1.Point1.ToPointD().DistanceTo(w2);
                        Area = (Hemline1.Length + Hemline2.Length) * Waist1.Length / 2;
                        BaryCenter = Utility.GetBaryCenter(new PointD[] { Hemline1.Point1.ToPointD(), Waist1.Point1.ToPointD(), Hemline2.Point1.ToPointD(), w2 });
                    }
                    else
                    {
                        return;
                    }
                    break;
                case 2:
                    if (component == Hemline1)
                    {
                        SpareCoordinate = Utility.GetCrossPoint(Hemline1.SpareCoordinate, Pad.kToPk(-1 / Hemline1.Slope), Waist2.Point1.Pxy, Hemline1.PSlope);
                        PointD w1, h2;
                        if (Pad.Coordinate == null)
                        {
                            w1 = Hemline1.SpareCoordinate;
                            h2 = SpareCoordinate;
                        }
                        else
                        {
                            w1 = Pad.Coordinate.PxyToXY(Hemline1.SpareCoordinate);
                            h2 = Pad.Coordinate.PxyToXY(SpareCoordinate);
                        }
                        double height = w1.DistanceTo(h2), db2len = h2.DistanceTo(Waist2.Point1.ToPointD());
                        Circumference = Waist2.Length + Hemline1.Length + height + db2len;
                        Area = (Hemline1.Length + db2len) * height / 2;
                        BaryCenter = Utility.GetBaryCenter(new PointD[] { Waist2.Point1.ToPointD(), Hemline1.Point1.ToPointD(), w1, h2 });
                    }
                    else
                    {
                        return;
                    }
                    break;
                case 3:
                    if (component == Waist2)
                    {
                        SpareCoordinate = Utility.GetCrossPoint(Hemline1.Point1.Pxy, Pad.kToPk(-1 / Hemline1.Slope), Waist2.SpareCoordinate, Hemline1.PSlope);
                        PointD h2, w1;
                        if (Pad.Coordinate == null)
                        {
                            h2 = Waist2.SpareCoordinate;
                            w1 = SpareCoordinate;
                        }
                        else
                        {
                            h2 = Pad.Coordinate.PxyToXY(Waist2.SpareCoordinate);
                            w1 = Pad.Coordinate.PxyToXY(SpareCoordinate);
                        }
                        double height = w1.DistanceTo(Hemline1.Point1.ToPointD()), db2len = h2.DistanceTo(w1);
                        Circumference = Waist2.Length + Hemline1.Length + height + db2len;
                        Area = (Hemline1.Length + db2len) * height / 2;
                        BaryCenter = Utility.GetBaryCenter(new PointD[] { Hemline1.Point1.ToPointD(), Waist2.Point1.ToPointD(), h2, w1 });
                    }
                    else
                    {
                        return;
                    }
                    break;
            }
            base.ComponentBuilding(component);
        }
        public override void InternalPrepare(PointBase movePoint, ShapeBase sender = null)
        {
            if (CountMovablePoints() == 2 && sender == null)
            {
                if (movePoint == Waist1.Point1)
                {
                    if (Waist2.Point1.Movable)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            rate = Hemline1.Length / Hemline2.Length;
                        }
                        else
                        {
                            rate = Hemline2.Length / Hemline1.Length;
                        }
                    }
                }
                else if (movePoint == Hemline1.Point1)
                {
                    if (Hemline2.Point1.Movable)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            rate = Hemline2.Length / Hemline1.Length;
                        }
                    }
                    else if (Waist2.Point1.Movable)
                    {
                        if (OrderIndex == 1 || OrderIndex == 2)
                        {
                            rate = Hemline2.Length / Hemline1.Length;
                        }
                    }
                }
                else if (movePoint == Hemline2.Point1)
                {
                    if (Hemline1.Point1.Movable)
                    {
                        if (OrderIndex == 1 || OrderIndex == 2)
                        {
                            rate = Hemline1.Length / Hemline2.Length;
                        }
                    }
                    else if (Waist2.Point1.Movable)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            rate = Hemline1.Length / Hemline2.Length;
                        }
                    }
                }
                else if (movePoint == Waist2.Point1)
                {
                    if (Hemline2.Point1.Movable)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            rate = Hemline2.Length / Hemline1.Length;
                        }
                    }
                    else if (Hemline1.Point1.Movable)
                    {
                        if (OrderIndex == 1 || OrderIndex == 2)
                        {
                            rate = Hemline1.Length / Hemline2.Length;
                        }
                    }
                }
            }
            base.InternalPrepare(movePoint, sender);
        }
        public override PointCollectionBase[] GetInPointMovingRange(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 1:
                    if (movePoint == Waist1.Point1)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            return new PointCollectionBase[] { new DiscontinuityPoint(Utility.GetCrossPoint(Hemline2.Point1.NewXY, Hemline1.NewSlope, Hemline1.Point1.NewXY, -1 / Hemline1.NewSlope)) };
                        }
                        else
                        {
                            return new PointCollectionBase[] { new DiscontinuityPoint(Utility.GetCrossPoint(Hemline1.Point1.NewXY, Hemline2.NewSlope, Hemline2.Point1.NewXY, -1 / Hemline2.NewSlope)) };
                        }
                    }
                    else if (movePoint == Waist2.Point1)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            return new PointCollectionBase[] { new Ray(Hemline1.Point1.NewXY, Waist1.Point1.NewXY.GetAngle(Hemline2.Point1.NewXY)) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Hemline2.Point1.NewXY, Waist1.NewSlope) } } };
                        }
                        else
                        {
                            return new PointCollectionBase[] { new Ray(Hemline2.Point1.NewXY, Waist1.Point1.NewXY.GetAngle(Hemline1.Point1.NewXY)) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Hemline1.Point1.NewXY, Waist1.NewSlope) } } };
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            return new PointCollectionBase[] { new DiscontinuityPoint(Utility.GetCrossPoint(Waist2.Point1.NewXY, Hemline2.NewSlope, Waist1.Point1.NewXY, -1 / Hemline2.NewSlope)) };
                        }
                        else
                        {
                            return new PointCollectionBase[] { new Ray(Waist1.Point1.NewXY, Hemline2.Point1.NewXY.GetAngle(Waist2.Point1.NewXY)) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Waist2.Point1.NewXY, Waist1.NewSlope) } } };
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        if (OrderIndex == 0 || OrderIndex == 3)
                        {
                            return new PointCollectionBase[] { new Ray(Waist1.Point1.NewXY, Hemline1.Point1.NewXY.GetAngle(Waist2.Point1.NewXY)) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Waist2.Point1.NewXY, Waist1.NewSlope) } } };
                        }
                        else
                        {
                            return new PointCollectionBase[] { new DiscontinuityPoint(Utility.GetCrossPoint(Waist2.Point1.NewXY, Hemline1.NewSlope, Waist1.Point1.NewXY, -1 / Hemline1.NewSlope)) };
                        }
                    }
                    break;
                case 2:
                    if (movePoint == Waist1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            return new PointCollectionBase[] { new PointCollection.Circle((Hemline1.Point1.NewXY + Hemline2.Point1.NewXY) / 2, Hemline1.Point1.NewXY.DistanceTo(Hemline2.Point1.NewXY) / 2) };
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 1 || OrderIndex == 2)
                            {
                                PointD crs = Utility.GetCrossPoint(Hemline2.Point1.NewXY, -1 / Hemline2.NewSlope, Waist2.Point1.NewXY, Waist2.NewSlope);
                                return new PointCollectionBase[] { new Ray(crs, crs.GetAngle(Hemline2.Point1.NewXY)) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist2.NewMidPoint, Waist2.Length / 2) };
                            }
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                PointD crs = Utility.GetCrossPoint(Hemline1.Point1.NewXY, -1 / Hemline1.NewSlope, Waist2.Point1.NewXY, Waist2.NewSlope);
                                return new PointCollectionBase[] { new Ray(crs, crs.GetAngle(Hemline1.Point1.NewXY)) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist2.NewMidPoint, Waist2.Length / 2) };
                            }
                        }
                    }
                    else if (movePoint == Waist2.Point1)
                    {
                        if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 1 || OrderIndex == 2)
                            {
                                return new PointCollectionBase[] { new StraightLine(Hemline2.Point1.NewXY, -1 / Waist1.NewSlope) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Waist1.Point1.NewXY, -1 / Hemline2.NewSlope, Hemline2.Point1.NewXY) };
                            }
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                return new PointCollectionBase[] { new StraightLine(Hemline1.Point1.NewXY, -1 / Waist1.NewSlope) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Waist1.Point1.NewXY, -1 / Hemline1.NewSlope, Hemline1.Point1.NewXY) };
                            }
                        }
                        else if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline1.Point1.NewXY, -1 / Hemline1.Point1.NewXY.GetSlope(Hemline2.Point1.NewXY), Hemline2.Point1.NewXY) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline2.Point1.NewXY, -1 / Hemline2.Point1.NewXY.GetSlope(Hemline1.Point1.NewXY), Hemline1.Point1.NewXY) };
                            }
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist2.NewMidPoint, Waist2.NewLength / 2) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline2.Point1.NewXY, -1 / Hemline2.NewSlope, Waist2.Point1.NewXY) };
                            }
                        }
                        else if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                PointD crs = Utility.GetCrossPoint(Waist1.Point1.NewXY, -1 / Hemline2.NewSlope, Hemline2.Point1.NewXY, Waist2.NewSlope);
                                return new PointCollectionBase[] { new Ray(crs, crs.GetAngle(Waist1.Point1.NewXY)) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLine(Waist1.Point1.NewXY, -1 / Waist1.NewSlope) };
                            }
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                return new PointCollectionBase[] { new PointCollection.Circle((Waist1.Point1.NewXY + Waist2.Point1.NewXY) / 2, Waist1.Point1.NewXY.DistanceTo(Waist2.Point1.NewXY) / 2) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Waist1.Point1.NewXY, -1 / Waist1.Point1.NewXY.GetSlope(Waist2.Point1.NewXY), Waist2.Point1.NewXY) };
                            }
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Hemline1.Point1.NewXY, -1 / Hemline1.NewSlope, Waist2.Point1.NewXY) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new OutCircle(Waist2.NewMidPoint, Waist2.NewLength / 2) };
                            }
                        }
                        else if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                return new PointCollectionBase[] { new StraightLine(Waist1.Point1.NewXY, -1 / Waist1.NewSlope) };
                            }
                            else
                            {
                                PointD crs = Utility.GetCrossPoint(Waist1.Point1.NewXY, -1 / Hemline1.NewSlope, Hemline1.Point1.NewXY, Waist2.NewSlope);
                                return new PointCollectionBase[] { new Ray(crs, crs.GetAngle(Waist1.Point1.NewXY)) };
                            }
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 1 || OrderIndex == 2)
                            {
                                return new PointCollectionBase[] { new PointCollection.Circle((Waist1.Point1.NewXY + Waist2.Point1.NewXY) / 2, Waist1.Point1.NewXY.DistanceTo(Waist2.Point1.NewXY) / 2) };
                            }
                            else
                            {
                                return new PointCollectionBase[] { new StraightLineOneSide(Waist1.Point1.NewXY, -1 / Waist1.Point1.NewXY.GetSlope(Waist2.Point1.NewXY), Waist2.Point1.NewXY) };
                            }
                        }
                    }
                    break;
            }
            return base.GetInPointMovingRange(movePoint, sender);
        }
        public override void InternalPointMove(PointBase movePoint, Base sender = null)
        {
            switch (CountMovablePoints())
            {
                case 2:
                    PointD tmp;
                    if (movePoint == Waist1.Point1)
                    {
                        if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = rate * (Hemline2.Point1.NewPxy - Waist1.Point1.NewPxy) + Hemline1.Point1.NewPxy;
                            }
                            else
                            {
                                tmp = rate * (Hemline1.Point1.NewPxy - Waist1.Point1.NewPxy) + Hemline2.Point1.NewPxy;
                            }
                            Waist2.Point1.Move(tmp);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Utility.GetCrossPoint(Waist2.Point1.NewXY, Hemline2.NewSlope, movePoint.NewXY, -1 / Hemline2.NewSlope);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline2.NewSlope, Waist2.Point1.NewXY, Waist2.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline1.Point1.Move(tmp, OrderIndex == 0 || OrderIndex == 3);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 1 || OrderIndex == 2)
                            {
                                tmp = Utility.GetCrossPoint(Waist2.Point1.NewXY, Hemline1.NewSlope, movePoint.NewXY, -1 / Hemline1.NewSlope);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline1.NewSlope, Waist2.Point1.NewXY, Waist2.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline2.Point1.Move(tmp, OrderIndex == 1 || OrderIndex == 2);
                        }
                    }
                    else if (movePoint == Waist2.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Utility.GetCrossPoint(Hemline2.Point1.NewXY, Hemline1.NewSlope, Hemline1.Point1.NewXY, -1 / Hemline1.NewSlope);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(Hemline1.Point1.NewXY, Hemline2.NewSlope, Hemline2.Point1.NewXY, -1 / Hemline2.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist1.Point1.Move(tmp, true);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline2.NewSlope, Waist1.Point1.NewXY, -1 / Hemline2.NewSlope);
                            }
                            else
                            {
                                tmp = Waist1.Point1.NewXY.Offset(Hemline2.Point1.NewXY.GetAngle(movePoint.NewXY), rate * Hemline2.NewLength);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline1.Point1.Move(tmp, OrderIndex == 0 || OrderIndex == 3);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Waist1.Point1.NewXY.Offset(Hemline1.Point1.NewXY.GetAngle(movePoint.NewXY), Hemline1.NewLength * rate);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline1.NewSlope, Waist1.Point1.NewXY, -1 / Hemline1.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Hemline2.Point1.Move(tmp, OrderIndex == 1 || OrderIndex == 2);
                        }
                    }
                    else if (movePoint == Hemline1.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Utility.GetCrossPoint(Hemline2.Point1.NewXY, Hemline1.NewSlope, movePoint.NewXY, -1 / Hemline1.NewSlope);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline2.NewSlope, Hemline2.Point1.NewXY, -1 / Hemline2.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist1.Point1.Move(tmp, true);
                        }
                        else if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline2.NewSlope, Hemline2.Point1.NewXY, Waist2.NewSlope);
                            }
                            else
                            {
                                tmp = Hemline2.Point1.NewXY.Offset(Waist1.Point1.NewXY.GetAngle(movePoint.NewXY), rate * Hemline1.NewLength);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist2.Point1.Move(tmp);
                        }
                        else if (Hemline2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = rate * (Waist2.Point1.NewPxy - movePoint.NewPxy) + Waist1.Point1.NewPxy;
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(Waist2.Point1.NewXY, Hemline1.NewSlope, Waist1.Point1.NewXY, -1 / Hemline1.NewSlope);
                                if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            }
                            Hemline2.Point1.Move(tmp, OrderIndex == 1 || OrderIndex == 2);
                        }
                    }
                    else if (movePoint == Hemline2.Point1)
                    {
                        if (Waist1.Point1.Movable)
                        {
                            if (OrderIndex == 1 || OrderIndex == 2)
                            {
                                tmp = Utility.GetCrossPoint(Hemline1.Point1.NewXY, Hemline2.NewSlope, movePoint.NewXY, -1 / Hemline2.NewSlope);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline1.NewSlope, Hemline1.Point1.NewXY, -1 / Hemline1.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist1.Point1.Move(tmp, true);
                        }
                        else if (Waist2.Point1.Movable)
                        {
                            if (OrderIndex == 0 || OrderIndex == 3)
                            {
                                tmp = Hemline1.Point1.NewXY.Offset(Waist1.Point1.NewXY.GetAngle(movePoint.NewXY), Hemline2.NewLength * rate);
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(movePoint.NewXY, Hemline1.NewSlope, Hemline1.Point1.NewXY, Waist2.NewSlope);
                            }
                            if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            Waist2.Point1.Move(tmp);
                        }
                        else if (Hemline1.Point1.Movable)
                        {
                            if (OrderIndex == 1 || OrderIndex == 2)
                            {
                                tmp = rate * (Waist2.Point1.NewPxy - movePoint.NewPxy) + Waist1.Point1.NewPxy;
                            }
                            else
                            {
                                tmp = Utility.GetCrossPoint(Waist2.Point1.NewXY, Hemline2.NewSlope, Waist1.Point1.NewXY, -1 / Hemline2.NewSlope);
                                if (Pad.Coordinate != null) tmp = Pad.Coordinate.XYToPxy(tmp);
                            }
                            Hemline1.Point1.Move(tmp, OrderIndex == 0 || OrderIndex == 3);
                        }
                    }
                    return;
            }
            base.InternalPointMove(movePoint, sender);
        }
        public override bool CanDrawVirtual
        {
            get
            {
                switch (OrderIndex)
                {
                    case 0:
                        return Waist2 != null;
                    case 1:
                        return Hemline2 != null;
                    case 2:
                        return Hemline1 != null;
                    case 3:
                        return Waist2 != null;
                }
                return base.CanDrawVirtual;
            }
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            if (CanDrawVirtual)
            {
                switch (OrderIndex)
                {
                    case 0:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Waist1.Point1.Pxy.ToPointF(), Hemline1.Point1.Pxy.ToPointF(), Waist2.Point1.Pxy.ToPointF(), Waist2.SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Waist2.SpareCoordinate_, Waist1.Point1.Pxy);
                        break;
                    case 1:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Hemline1.Point1.Pxy.ToPointF(), Waist1.Point1.Pxy.ToPointF(), Hemline2.Point1.Pxy.ToPointF(), Hemline2.SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Hemline2.SpareCoordinate_, Hemline1.Point1.Pxy);
                        break;
                    case 2:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Waist2.Point1.Pxy.ToPointF(), Hemline1.Point1.Pxy.ToPointF(), Hemline1.SpareCoordinate_.ToPointF(), SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Hemline1.SpareCoordinate_, SpareCoordinate_);
                        gra.DrawLineSegment(SpareCoordinate_, Waist2.Point1.Pxy);
                        gra.DrawPoint(SpareCoordinate_);
                        break;
                    case 3:
                        gra.FillPolygon(Core.Helper.Painter.VirtualBrush, new PointF[] { Hemline1.Point1.Pxy.ToPointF(), Waist2.Point1.Pxy.ToPointF(), Waist2.SpareCoordinate_.ToPointF(), SpareCoordinate_.ToPointF() });
                        gra.DrawLineSegment(Waist2.SpareCoordinate_, SpareCoordinate_);
                        gra.DrawLineSegment(SpareCoordinate_, Hemline1.Point1.Pxy);
                        gra.DrawPoint(SpareCoordinate_);
                        break;
                }
            }
        }
        protected override void ClickOrder(IList<PointCreatingArgs> args, int clickTimes, Predicate<PointCreatingArgs> act)
        {
            if (act == null) return;
            switch (OrderIndex)
            {
                case 1:
                    if (!act(args[1])) return;
                    if (!act(args[0])) return;
                    if (!act(args[3])) return;
                    if (!act(args[2])) return;
                    return;
                case 2:
                    if (!act(args[2])) return;
                    if (!act(args[1])) return;
                    if (!act(args[0])) return;
                    if (!act(args[3])) return;
                    return;
                case 3:
                    if (!act(args[1])) return;
                    if (!act(args[2])) return;
                    if (!act(args[3])) return;
                    if (!act(args[0])) return;
                    return;
            }
            base.ClickOrder(args, clickTimes, act);
        }
        public override void CreateComponents()
        {
            switch (OrderIndex)
            {
                case 0:
                    if (Waist1 == null)
                    {
                        Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("RightAngleWaist")}", false) { SpareCoordinate_ = SpareCoordinate_, };
                        Waist1.CreateComponents($"{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}2");
                    }
                    else if (Hemline1 == null)
                    {
                        Waist1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2");
                        Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false) { AllowFix = false };
                        Hemline1.CreateComponents(Waist1.Point2);
                    }
                    else if (Waist2 == null)
                    {
                        Hemline1.CreateComponents($"{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new StraightLine(Hemline1.Point1.ToPointD(), -1 / Waist1.Slope) });
                        Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("SlantingWaist")}", false);
                        Waist2.CreateComponents(Hemline1.Point2);
                    }
                    else
                    {
                        Waist2.CreateComponents($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new Ray(Waist1.Point1.ToPointD(), Hemline1.Point1.ToPointD().GetAngle(Waist2.Point1.ToPointD())) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Waist2.Point1.ToPointD(), Waist1.Slope) } } });
                        Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                        Hemline2.CreateComponents(Waist2.Point2, Waist1.Point1);
                        base.CreateComponents();
                    }
                    break;
                case 1:
                    if (Hemline1 == null)
                    {
                        Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                        Hemline1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2");
                    }
                    else if (Waist1 == null)
                    {
                        Hemline1.CreateComponents($"{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                        Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("RightAngleWaist")}", false) { AllowFix = false };
                        Waist1.CreateComponents(Hemline1.Point2);
                    }
                    else if (Hemline2 == null)
                    {
                        Waist1.CreateComponents($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new StraightLine(Waist1.Point1.ToPointD(), -1 / Hemline1.Slope) });
                        Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                        Hemline2.CreateComponents(Waist1.Point2);
                    }
                    else
                    {
                        Hemline2.CreateComponents($"{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new Ray(Hemline2.Point1.ToPointD(), Waist1.Point1.ToPointD().GetAngle(Hemline1.Point1.ToPointD())) { Exceptions = new HashSet<PointCollectionBase>() { new StraightLine(Hemline1.Point1.ToPointD(), Waist1.Slope) } } });
                        Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("SlantingWaist")}", false);
                        Waist2.CreateComponents(Hemline2.Point2, Hemline1.Point1);
                        base.CreateComponents();
                    }
                    break;
                case 2:
                    if (Waist2 == null)
                    {
                        Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("SlantingWaist")}", false) { SpareCoordinate_ = SpareCoordinate_, };
                        Waist2.CreateComponents($"{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                    }
                    else if (Hemline1 == null)
                    {
                        Waist2.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2");
                        Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false);
                        Hemline1.CreateComponents(Waist2.Point2);
                    }
                    else
                    {
                        Hemline1.CreateComponents($"{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] { new OutCircle(Waist2.MidPoint, Waist2.Length / 2) });
                        Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("RightAngleWaist")}", false);
                        Waist1.CreateComponents(Hemline1.Point2);
                        Flags.ShieldCtrl(() => { Waist1.CreateComponents(Pad.CreatePoint($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2", SpareCoordinate, false)); });
                        Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                        Hemline2.CreateComponents(Waist1.Point2, Waist2.Point1);
                        base.CreateComponents();
                    }
                    break;
                case 3:
                    if (Hemline1 == null)
                    {
                        Hemline1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}1", false) { SpareCoordinate_ = SpareCoordinate_, };
                        Hemline1.CreateComponents($"{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2");
                    }
                    else if (Waist2 == null)
                    {
                        Hemline1.CreateComponents($"{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}1{Resources.Join}{Resources.Translate("EndPoint")}2");
                        Waist2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("SlantingWaist")}", false);
                        Waist2.CreateComponents(Hemline1.Point2);
                    }
                    else
                    {
                        Waist2.CreateComponents($"{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("SlantingWaist")}{Resources.Join}{Resources.Translate("EndPoint")}2", new PointCollectionBase[] {new CustomCollection((PointD pt)=>
                        {
                            return pt.GetProjectivePoint(Hemline1.Point1.ToPointD(), -1 / Hemline1.Slope);
                        },
                        (PointD pt) => 
                        {
                            return Utility.OnSameSide(Hemline1.Point1.ToPointD(), -1 / Hemline1.Slope, pt, Waist2.Point1.ToPointD());
                        }) });
                        Hemline2 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("Hemline")}2", false);
                        Hemline2.CreateComponents(Waist2.Point2);
                        Flags.ShieldCtrl(() => { Hemline2.CreateComponents(Pad.CreatePoint($"{Resources.Translate("RightAngleWaist")}{Resources.Join}{Resources.Translate("EndPoint")}1/{Resources.Translate("Hemline")}2{Resources.Join}{Resources.Translate("EndPoint")}2", SpareCoordinate, false)); });
                        Waist1 = new TwoPointsLineSegment(Pad, $"{Resources.Translate("RightAngleWaist")}", false);
                        Waist1.CreateComponents(Hemline2.Point2, Hemline1.Point1);
                        base.CreateComponents();
                    }
                    break;
            }
        }
    }
}
